from twisted.internet.protocol import ClientFactory, Protocol
from twisted.internet import reactor, task

import struct

from twisted.python import log
import sys
import json
log.startLogging(sys.stdout)

from APIclient import APItest

'''
	@ cid: { 1:handle_verify,2:handle_chat }
	@ header:<cid> <length> <version>, length=12bytes
	@ content: json {'ch_from':ch_from, 'ch_to':ch_to, 'msg':msg}
'''



class EchoClient(Protocol):

	def __init__(self):

		self.command_func_dict = {
			101: self.handle_verify_resp,
			102: self.handle_chat_resp,
			103: self.handle_heartbeat_resp
		}
		self.version = 0
		self.state = "VERIFY"
		self.phone_number = ""


	def connectionMade(self):
		'''
		@链接建立处理事件
		'''
		log.msg("Connecting:", self.transport.getPeer())	#服务器端网络信息


	def connectionLost(self, reason):
		'''
		@链接断开处理事件
		'''
		log.msg("connection lost")


	def dataReceived(self, data):
		'''
        @数据包接收处理事件
        '''
		cid,length,self.version = struct.unpack('>3I', data[:12])
		content = data[12:length]

		if self.state == "VERIFY" and cid == 101:
			self.handle_verify_resp(content)
		else:
			self.handle_data(cid, content)


	def handle_data(self, cid, pack_data):
		'''
		@句柄映射调用
		'''
		self.command_func_dict[cid](pack_data)


	def handle_verify_resp(self, pack_data):
		'''
		@应答服务器鉴权包处理事件
		@根据服验证结果，更新链接实例状态
		'''
		content = json.loads(pack_data.decode('utf-8'))
		code = content.get('code')

		if code == 1:
			log.msg('verify success')
		self.state = "DATA"
		log.msg('Client status: ' + self.state)


	def handle_chat_resp(self, pack_data):
		'''
		@应答服务器聊天包处理事件
		'''
		content = json.loads(pack_data.decode('utf-8'))

		ch_from = content.get('ch_from')
		ch_content = content.get('ch_content')
		log.msg("[Receivd %s][single_chat] :%s" % (ch_from, ch_content))


	def handle_heartbeat_resp(self,pack_data):
		pass


	def send_verify(self, phone_number, token):	
		'''
		@发送鉴权包
		'''
		content = json.dumps(dict(phone_number=phone_number, token=token))
		self.send_data(content, 1)


	def send_chat(self, ch_from, ch_to, ch_content):
		'''
		@发送聊天包
		'''
		content_pack = json.dumps(dict(ch_from=ch_from, ch_to=ch_to, ch_content=ch_content))
		self.send_data(content_pack, 2)


	def send_data(self, content, cid):
		'''
		@发送数据函数
		'''
		cid = cid
		length = 12 + len(content)
		version = self.version
		header = [cid, length, version]
		header_pack = struct.pack('>3I', *header)
		content_pack = content.encode('utf-8')
		self.transport.write(header_pack + content_pack)
		log.msg(b'Sending : ' + content_pack)


	def send_heartbeat(self):
		'''
        @发送心跳包
        '''
		cid = 3
		length = 12
		version = self.version
		header = [cid, length, version]
		header_pack = struct.pack('>3I', *header)
		self.transport.write(header_pack)
		log.msg(b'send_heartbeat:' + header_pack)



class EchoClientFactory(ClientFactory):

	def __init__(self):
		self.p = EchoClient()


	def startedConnecting(self, connector):
		log.msg("Started to connect")


	def buildProtocol(self, addr):
		log.msg("Connected.")
		return self.p



def main():

	cf = EchoClientFactory()
	from_phone_number = sys.argv[1]
	from_password = sys.argv[2]
	to_phone_numbers = '13641311764'

	BASE_URL = r'http://127.0.0.1'
	api = APItest(BASE_URL)
	u = api.login(from_phone_number, from_password)
	token = api.token

	# 发送验证
	reactor.callLater(1, cf.p.send_verify, from_phone_number, token)
	
	# 发送一次 聊天业务
	# reactor.callLater(5, cf.p.send_chat, from_phone_number, to_phone_numbers, 'Hay')   

	# 循环发送 心跳业务
	task_send_heartbeat = task.LoopingCall(cf.p.send_heartbeat)
	task_send_heartbeat.start(2, now=False)	#每隔3秒发一次

	reactor.connectTCP('127.0.0.1', 7707, cf) 
	reactor.run()



if __name__ == '__main__':
	#
	main()
	